﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Jb.Common.Extensions;
using Jb.Web.ViewModels;
using Jb.Domain;
using System.Text;

namespace Jb.Web.Utility
{
    public static class ApplicationCache
    {
        private const String CATEGORIES = "Categories";
        private const String USER_GROUPS = "UserGroups";

        //private static List<CategoryViewModel> _categories = null;
        /// <summary>
        /// Caches the Categories
        /// </summary>
        public static List<CategoryViewModel> Categories
        {
            get
            {
                List<CategoryViewModel> categories = HttpContext.Current.Application[CATEGORIES] as List<CategoryViewModel>;
                if (categories == null || categories.Count == 0)
                {
                    RefreshCategoryCache();
                    categories = HttpContext.Current.Application[CATEGORIES] as List<CategoryViewModel>;
                }
                return categories;
            }
        }

        /// <summary>
        /// Refreshes the category cache
        /// </summary>
        public static void RefreshCategoryCache()
        {
            JbEntities context = new JbEntities();
            List<Category> categories = context.Categories.Include("ParentCategory").Include("ChildCategories").ToList();
            HttpContext.Current.Application[CATEGORIES] = AutoMapper.Mapper.Map<List<Category>, List<CategoryViewModel>>(categories);            
        }

        /// <summary>
        /// Cache of User Groups
        /// </summary>
        public static List<GroupViewModel> UserGroups
        {
            get
            {
                List<GroupViewModel> userGroups = HttpContext.Current.Application[USER_GROUPS] as List<GroupViewModel>;
                if (userGroups == null || userGroups.Count == 0)
                {
                    RefreshUserGroups();
                    userGroups = HttpContext.Current.Application[USER_GROUPS] as List<GroupViewModel>;
                }
                return userGroups;
            }
        }

        /// <summary>
        /// Refreshes the user group cache
        /// </summary>
        public static void RefreshUserGroups()
        {
            JbEntities context = new JbEntities();
            List<Group> groups = context.Groups.ToList();
            List<GroupViewModel> groupsViewModel = AutoMapper.Mapper.Map<List<Group>, List<GroupViewModel>>(groups);
            HttpContext.Current.Application[USER_GROUPS] = groupsViewModel;
        }

        /// <summary>
        /// Caches the Site Configuration that are stored in the Database and managed by Administrator
        /// </summary>
        public static List<SiteConfiguration> SiteConfigurations
        {
            get
            {
                List<SiteConfiguration> configs = HttpContext.Current.Application["SITE_CONFIGURATIONS"] as List<SiteConfiguration>;
                if (configs == null || configs.Count == 0)
                {
                    RefreshConfigurationCache();
                    configs = HttpContext.Current.Application["SITE_CONFIGURATIONS"] as List<SiteConfiguration>;
                }
                return configs;
            }
        }
        /// <summary>
        /// Refreshes the category cache
        /// </summary>
        public static void RefreshConfigurationCache()
        {
            JbEntities context = new JbEntities();
            List<SiteConfiguration> configs = context.SiteConfigurations.ToList();
            HttpContext.Current.Application["SITE_CONFIGURATIONS"] = configs; //AutoMapper.Mapper.Map<List<Category>, List<CategoryViewModel>>(categories);
        }

        /// <summary>
        /// Mime Types for different file extension. Currently holds only the content types for resume documents.
        /// </summary>
        public static Dictionary<String, String> MimeTypes
        {
            get
            {
                Dictionary<String, String> configs = HttpContext.Current.Application["JB_MIME_TYPES"] as Dictionary<String, String>;
                if (configs == null || configs.Count == 0)
                {
                    InitMimeTypes();
                    configs = HttpContext.Current.Application["JB_MIME_TYPES"] as Dictionary<String, String>;
                }
                return configs;
            }
        }

        /// <summary>
        /// Initializes Supported MIME Types by JobBoard
        /// </summary>
        public static void InitMimeTypes()
        {
            Dictionary<String, String> mimeTypes = new Dictionary<String, String>
            {
                //'Images'
                //{".bmp", "image/bmp"},
                //{".gif", "image/gif"},
                //{".jpeg", "image/jpeg"},
                //{".jpg", "image/jpeg"},
                //{".png", "image/png"},
                //{".tif", "image/tiff"},
                //{".tiff", "image/tiff"},
                //'Documents'
                {".doc", "application/msword"},
                {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
                {".pdf", "application/pdf"},
                {".txt", "text/plain"},
                //'Slideshows'
                //{".ppt", "application/vnd.ms-powerpoint"},
                //{".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
                //'Data'
                //{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
                //{".xls", "application/vnd.ms-excel"},
                //{".csv", "text/csv"},
                //{".xml", "text/xml"},                
                //'Compressed Folders'
                //{".zip", "application/zip"},
                //'Audio'
                //{".ogg", "application/ogg"},
                //{".mp3", "audio/mpeg"},
                //{".wma", "audio/x-ms-wma"},
                //{".wav", "audio/x-wav"},
                //'Video'
                //{".wmv", "audio/x-ms-wmv"},
                //{".swf", "application/x-shockwave-flash"},
                //{".avi", "video/avi"},
                //{".mp4", "video/mp4"},
                //{".mpeg", "video/mpeg"},
                //{".mpg", "video/mpeg"},
                //{".qt", "video/quicktime"}
            };
            HttpContext.Current.Application["JB_MIME_TYPES"] = mimeTypes;
        }        

        #region Company and Content URL Routes

        /// <summary>
        /// Represents the Company Routes in the Application Cache
        /// </summary>
        public static String CompanyRoutes
        {
            get
            {
                String routes = HttpContext.Current.Application["COMPANY_ROUTES"] as String;
                if (routes.IsEmpty() || String.Compare(routes, AppConstants.ValueOf.UNKNOWN, true) == 0)
                {
                    RefreshCompanyRouteCache(false);
                    routes = HttpContext.Current.Application["COMPANY_ROUTES"] as String;
                }
                return routes;
            }
        }

        /// <summary>
        /// Refreshes Company URL Routes in Application Cache
        /// </summary>
        /// <param name="forceRebuild"></param>
        public static void RefreshCompanyRouteCache(bool forceRebuild)
        {
            String routes = BuildCompanyUrlRoutes(forceRebuild);
            HttpContext.Current.Application["COMPANY_ROUTES"] = routes;
        }

        /// <summary>
        /// Represents the Content Routes in the Application Cache
        /// </summary>
        public static String ContentRoutes
        {
            get
            {
                String routes = HttpContext.Current.Application["CONTENT_ROUTES"] as String;
                if (routes.IsEmpty() || String.Compare(routes, AppConstants.ValueOf.UNKNOWN, true) == 0)
                {
                    RefreshContentRouteCache(false);
                    routes = HttpContext.Current.Application["CONTENT_ROUTES"] as String;
                }
                return routes;
            }
        }

        /// <summary>
        /// Refreshes Content URL Routes in Application Cache
        /// </summary>
        /// <param name="forceRebuild"></param>
        public static void RefreshContentRouteCache(bool forceRebuild)
        {
            String routes = BuildContentUrlRoutes(forceRebuild);
            HttpContext.Current.Application["CONTENT_ROUTES"] = routes;
        }

        /// <summary>
        /// Builds Company URL Routes and Saves them into the Database if forced
        /// </summary>
        /// <param name="forceRebuild"></param>
        /// <returns></returns>
        public static String BuildCompanyUrlRoutes(bool forceRebuild)
        {
            JbEntities context = new JbEntities();
            if (!context.IsConnected())
                return AppConstants.ValueOf.UNKNOWN;

            SiteConfiguration config = context.SiteConfigurations.FirstOrDefault(P => String.Compare(P.ConfKey, SiteConfigReader.Constants.COMPANY_URLS, true) == 0);//SiteConfigReader.GetConfig(SiteConfigReader.Constants.COMPANY_URLS);
            if (config == null)
            {
                config = new SiteConfiguration();
                config.ConfKey = SiteConfigReader.Constants.COMPANY_URLS;
                //context.Configurations.AddObject(config);
                context.AddToSiteConfigurations(config);
            }
            if (config.ConfValue.IsEmpty() || String.Compare(config.ConfValue, AppConstants.ValueOf.UNKNOWN, true) == 0 || forceRebuild)
            {
                var companies = context.Companies.ToList();
                StringBuilder sb = new StringBuilder(10);
                foreach (Company company in companies)
                {
                    if(company.Url.IsNullOrEmpty())
                        company.Url = company.Name.ToSeoUrl();

                    if (sb.Length == 0)
                        sb.Append(company.Url);
                    else
                        sb.AppendFormat("|{0}", company.Url);
                }
                if (sb.Length == 0)
                    sb.Append(AppConstants.ValueOf.UNKNOWN);
                if (forceRebuild )//|| config.ConfValue.IsEmpty() || String.Compare(config.ConfValue, AppConstants.ValueOf.UNKNOWN, true) == 0)
                {
                    config.ConfValue = sb.ToString();                    
                    config.ModifiedBy = SessionCache.CurrentUser == null ? -1 : SessionCache.CurrentUser.ID;
                    config.ModifiedOn = DateTime.Now;
                    context.SaveChanges();
                    ApplicationCache.RefreshConfigurationCache();
                }
                return sb.ToString();
            }
            return config.ConfValue;
        }
        
        /// <summary>
        /// Builds Content URL Routes and Saves them into the Database if forced
        /// </summary>
        /// <param name="forceRebuild"></param>
        /// <returns></returns>
        public static String BuildContentUrlRoutes(bool forceRebuild)
        {
            JbEntities context = new JbEntities();
            if (!context.IsConnected())
                return AppConstants.ValueOf.UNKNOWN;

            SiteConfiguration config = context.SiteConfigurations.FirstOrDefault(P => String.Compare(P.ConfKey, SiteConfigReader.Constants.CONTENT_URLS, true) == 0);//SiteConfigReader.GetConfig(SiteConfigReader.Constants.CONTENT_URLS);
            if (config == null)
            {
                config = new SiteConfiguration();
                config.ConfKey = SiteConfigReader.Constants.CONTENT_URLS;                
                //context.Configurations.AddObject(config);
                context.AddToSiteConfigurations(config);
            }
            if (config.ConfValue.IsEmpty() || String.Compare(config.ConfValue, AppConstants.ValueOf.UNKNOWN, true) == 0 || forceRebuild)
            {
                //var contents = context.Contents;
                StringBuilder sb = new StringBuilder(10);
                foreach (Content content in context.Contents)
                {
                    if(content.Url.IsNullOrEmpty())
                        content.Url = content.Title.ToSeoUrl();

                    if (sb.Length == 0)
                        sb.Append(content.Url);
                    else
                        sb.AppendFormat("|{0}", content.Url);
                }
                if (sb.Length == 0)
                    sb.Append(AppConstants.ValueOf.UNKNOWN);
                if (forceRebuild)
                {
                    config.ConfValue = sb.ToString();
                    config.ModifiedOn = DateTime.Now;
                    config.ModifiedBy = SessionCache.CurrentUser == null ? -1 : SessionCache.CurrentUser.ID;
                    context.SaveChanges();
                }
                return sb.ToString();
            }
            return config.ConfValue;
        }
        
        #endregion
    }
}